Skip to content

tests: Test that when a node loses state and the closing transaction has HTLC outputs#8887

Open
enaples wants to merge 2 commits intoElementsProject:masterfrom
enaples:test-anchor-channel-state-loss
Open

tests: Test that when a node loses state and the closing transaction has HTLC outputs#8887
enaples wants to merge 2 commits intoElementsProject:masterfrom
enaples:test-anchor-channel-state-loss

Conversation

@enaples
Copy link
Copy Markdown
Collaborator

@enaples enaples commented Feb 6, 2026

Scenario

In order to reproduce the issue reported in #8880 where onchaind makes node crashes after CLN has lost a channel state (due to database deletion/corruption) and encounters a force-close transaction containing HTLC outputs that it no longer has knowledge of.

Background

A commitment transaction with anchors typically has 5 outputs (here an example):

  1. Local anchor - for fee bumping
  2. Remote anchor - for fee bumping
  3. to_local output - funds belonging to the broadcaster (timelocked)
  4. to_remote output - funds belonging to the counterparty
    HTLC output(s) - pending payments in-flight

When a node loses its database, it loses:

  • The commitment number and per-commitment secrets
  • Knowledge of any in-flight HTLCs
  • The scripts needed to identify and claim HTLC outputs

Test Steps

  1. Create two nodes with anchors (default). l1 will lose state, l2 has a disconnect trigger on WIRE_UPDATE_FULFILL_HTLC
  2. l2 funds a channel to l1 (1M sats)
  3. l2 pays l1400k sats so both sides have funds
  4. l1 starts a payment to l2. l2 receives the HTLC but disconnects before sending the fulfill message
  5. Sign l2's commitment transaction which contains the pending HTLC (verifies 4+ outputs: 2 anchors + HTLC + balances)
  6. Stop l1, delete its database
  7. Restart l1 and use emergencyrecover() to stub the channel
  8. Reconnect to l2, which triggers the bogus reestablish
  9. The captured commitment is broadcast on-chain
  10. l1's onchaind fails with "Could not find resolution for output X" because it doesn't know about the HTLC

The test will fail before its end, when l1 will resing with bitcoind, with the command sync_blockheight(bitcoind, [l1, l2])

Changelog-None

@enaples enaples added this to the 26.06 milestone Mar 13, 2026
@madelinevibes madelinevibes added the QA Blockstream QA team have reproduced, or a test has been created! Look for the linked PR/Issue label May 4, 2026
@cdecker cdecker force-pushed the test-anchor-channel-state-loss branch from 65d9217 to 3a62fff Compare May 4, 2026 10:25
@cdecker
Copy link
Copy Markdown
Member

cdecker commented May 4, 2026

Rebased on top of master to see if it passes.

@cdecker
Copy link
Copy Markdown
Member

cdecker commented May 4, 2026

@enaples, please address the linter issues.

@cdecker cdecker removed this from the v26.06 milestone May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

QA Blockstream QA team have reproduced, or a test has been created! Look for the linked PR/Issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants